#pragma once

#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>

#include <cstring>
#include <iostream>
#include <string>
// 引入自定义的日志库
#include "log.hpp"

// 定义默认端口号
const int defaultport = 8080; // 默认端口号 将绑定该端口号

// 定义服务器类
class Server
{
public:
    // 构造函数，初始化服务器端口（默认为 defaultport）
    Server(uint16_t port = defaultport) : port_(port) {}

    // 初始化服务器，设置监听套接字
    void Init()
    {
        // 创建一个监听套接字
        listen_socket_ = socket(AF_INET, SOCK_STREAM, 0);

        int opt = 1;
        setsockopt(listen_socket_, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));

        if (listen_socket_ < 0)
        {
            // 如果创建失败，记录致命错误并退出
            lg(FATAL, "create listen socket fail");
            exit(1);
        }

        // 初始化本地地址结构体
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;         // 设置地址族为 IPv4
        local.sin_port = htons(port_);      // 设置端口号，使用网络字节序
        local.sin_addr.s_addr = INADDR_ANY; // 绑定到所有本地接口

        socklen_t len = sizeof(local);
        // 绑定套接字到指定的地址和端口
        if (bind(listen_socket_, (sockaddr *)&local, len) < 0)
        {
            // 如果绑定失败，记录致命错误并退出
            lg(FATAL, "bind error");
            exit(2);
        }

        // 开始监听传入的连接
        if (listen(listen_socket_, 1) < 0)
        {
            // 如果监听失败，记录致命错误并退出
            lg(FATAL, "listen error");
            exit(3);
        }
    }

    // 启动服务器
    void Start()
    {
        // 服务器主循环，暂时只是在此处休眠
        while (true)
        {
            struct sockaddr_in client;
            socklen_t size = sizeof(client);
            int sockfd = accept(listen_socket_, (struct sockaddr *)&client, &size);
            if (sockfd < 0)
            {
                lg(WARNING, "Accept fail...");
                exit(4);
            }

            sleep(10);
            lg(INFO, "sockfd :%d closed...", sockfd);
            close(sockfd);
        }
    }

private:
    int listen_socket_; // 监听套接字文件描述符
    uint16_t port_;     // 服务器端口号
};
